﻿package com.cw.war.ui
{
	import com.greensock.TweenLite;
	import com.greensock.easing.Circ;
	
	import flash.display.DisplayObject;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	
	import net.libra.ui.layer.LayerManager;
	
	/**
	 * 大地图操作器
	 * @date 2012.07.09
	 */
	public class Map extends EventDispatcher
	{
		private var _map:DisplayObject;
		private var _rectangle:Rectangle;    //代表分辨率的宽高
		private var _mdx:Number;    //鼠标按下时相对于map对象的x值
		private var _mdy:Number;    //鼠标按下时相对于map对象的y值
		
		private var _moveW:Number = 0;
		private var _moveH:Number = 0;
		
		private var _drag:Boolean;
		private var _dragable:Boolean;
		private var _resizeWithStage:Boolean;
		
		/**
		 * 创建一个大地图操作器
		 */
		public function Map(map:DisplayObject)
		{
			_map = map;
			_rectangle = new Rectangle();
			_mdx = _mdy = 0;
			_drag = false;
			_resizeWithStage = _dragable = true;
			_map.addEventListener(Event.ADDED_TO_STAGE, onAddToStage);
			_map.addEventListener(Event.REMOVED_FROM_STAGE, onRemovedFromStage);
			_map.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
		}
		
		/**
		 * 响应地图添加到舞台事件
		 * */
		private function onAddToStage(event:Event):void
		{
			_map.stage.addEventListener(Event.RESIZE, onResize);
			_map.stage.addEventListener(Event.MOUSE_LEAVE, onLeaveHandler);
			updateRect();
		}
		
		/**
		 * 响应地图从舞台移除事件
		 * */
		private function onRemovedFromStage(event:Event):void
		{
			_map.stage.removeEventListener(Event.RESIZE, onResize);
			_map.stage.removeEventListener(Event.MOUSE_LEAVE, onLeaveHandler);
			_map.stage.removeEventListener(MouseEvent.MOUSE_UP, onUpHandler);
			_map.stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMoveHandler);
		}
		
		/**
		 * 响应fp宽高改变事件
		 * */
		private function onResize(event:Event=null):void
		{
			updateRect();
			moveFirst(_map.x, _map.y, true);
		}
		
		/**
		 * 响应鼠标离开舞台事件(鼠标没有按下的情况下)
		 * */
		private function onLeaveHandler(event:Event):void
		{
			_drag = false;
		}
		
		/**
		 * 响应鼠标按下事件
		 * */
		private function onMouseDown(event:MouseEvent):void
		{
			if(_dragable)
			{
				_mdx = _map.mouseX;
				_mdy = _map.mouseY;
				_drag = true;
				_map.stage.addEventListener(MouseEvent.MOUSE_UP, onUpHandler);
				_map.stage.addEventListener(MouseEvent.MOUSE_MOVE, onMoveHandler);
			}
		}
		
		/**
		 * 响应鼠标移动事件
		 * */
		private function onMoveHandler(event:MouseEvent):void
		{
			if(_drag)
			{
				var pmx:Number = _map.parent.mouseX;
				var pmy:Number = _map.parent.mouseY;
				moveFirst(pmx, pmy, true);    //立即移动地图，内部调用doMove函数
				moveSecond(-pmx, -pmy, true);
				event.updateAfterEvent();
			}
		}
		
		/**
		 * 响应鼠标抬起事件
		 * */
		private function onUpHandler(event:MouseEvent):void
		{
			_mdx = _mdy = 0;
			_map.stage.removeEventListener(MouseEvent.MOUSE_UP, onUpHandler);
			_map.stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMoveHandler);
			_drag = false;    //延迟1秒发送时间
		}
		
		/**
		 * 立即移动地图
		 * @param toX 要移动到的x坐标，坐标为大于0的值，方法将自动转换
		 * @param toY 要移动到的y坐标，坐标为大于0的值，方法将自动转换
		 * @param dispatchEvent
		 */
		private function moveFirst(toX:Number, toY:Number, dispatchEvent:Boolean=false):void
		{
			doMove(toX, toY, 0, null, dispatchEvent);
		}
		
		/**
		 * 移动地图，方法将进行移动补间，将地图移动到目标点
		 * @param toX				要移动到的x坐标，坐标为大于0的值，方法将自动转换
		 * @param toY				要移动到的y坐标，坐标为大于0的值，方法将自动转换
		 * @param dispatchEvent		是否发送移动事件
		 * @param duration			移动时间
		 * @param easeFun			移动函数
		 */
		private function moveSecond(toX:Number, toY:Number, dispatchEvent:Boolean=false, duration:Number=0.3, easeFun:Function=null):void
		{
			if(!_drag)
			{
				if(easeFun == null)
				{
					easeFun = Circ.easeOut;
				}
				doMove(-toX, -toY, duration, easeFun, dispatchEvent);
			}
		}
		
		/**
		 * 实际拖拽操作,鼠标实际按下移动时
		 * moveFirst(px, py, 0, null, true);
		 * */
		private function doMove(toX:Number, toY:Number, duration:Number, easeFun:Function, dispatchEvent:Boolean):void
		{
			toX = getTargetX(toX);    //获得横向差值
			toY = getTargetY(toY);    //获得纵向差值
			if(duration == 0)
			{
				_map.x = _moveW = toX;
				_map.y = _moveH = toY;
				if(dispatchEvent)
				{
					fireMove();
				}
			}
			else
			{
				var onUpdate:Function = dispatchEvent ? fireMove : null;
				TweenLite.to(_map, duration, {x:toX, y:toY, ease:easeFun, onUpdate:onUpdate});
			}
		}

		public function moveToDistXY(moveW:Number, moveH:Number):void
		{
			_map.x = moveW;
			_map.y = moveH;
		}
		
		/**
		 * 获得横向差值
		 * */
		private function getTargetX(toX:Number):Number
		{
			var cha:Number = toX - _mdx;
			if(cha > _rectangle.left)    //(此时说明map.x大于0)_rectangle.left即_rectangle.x
			{
				cha = _rectangle.left;
			}
			else if(cha + _map.width < _rectangle.right)    //(此时说明map宽度小于分辨率w值)_rectangle.right即分辨率w值
			{
				cha = _rectangle.right - _map.width;
			}
			return cha;
		}
		
		/**
		 * 获得纵向差值
		 * */
		private function getTargetY(toY:Number):Number
		{
			var y:Number = toY - _mdy;
			if(y >= _rectangle.top)
			{
				y = _rectangle.top;
			}
			else if(y + _map.height <= _rectangle.bottom)
			{
				y = _rectangle.bottom - _map.height;
			}
			return y;
		}
		
		/**
		 * 设置地图的拖动范围
		 * @param x
		 * @param y
		 * @param width
		 * @param height
		 */
		public function setViewRect(x:Object, y:Number=0, width:Number=0, height:Number=0):void
		{
			if(x is Rectangle)
			{
				var r:Rectangle = x as Rectangle;
				_rectangle.x = r.x;
				_rectangle.y = r.y;
				_rectangle.width = r.width;
				_rectangle.height = r.height;
			}
			else
			{
				_rectangle.x = (x is Number) ? x as Number : 0;
				_rectangle.y = y;
				_rectangle.width = width;
				_rectangle.height = height;
			}
		}
		
		/**
		 * 设置是否随着屏幕自动调整视界
		 * @param b
		 */
		public function setResizeWithStage(b:Boolean):void
		{
			if(_resizeWithStage != b)
			{
				_resizeWithStage = b;
			}
		}
		
		/**
		 * 将指定的坐标移动到屏幕居中位置
		 * @param toX				要移动到的x坐标，坐标为大于0的值，方法将自动转换
		 * @param toY				要移动到的y坐标，坐标为大于0的值，方法将自动转换
		 * @param dispatchEvent
		 * @param duration			移动时间
		 * @param easeFun			移动函数
		 */
		public function moveToStageCenter(toX:Number, toY:Number, dispatchEvent:Boolean=false, duration:Number=0.3, easeFun:Function=null):void
		{
			if(!_drag)
			{
				var pt:Point = _map.localToGlobal(new Point(toX, toY));    //转换成全局坐标
				var stageCenterX:Number = LayerManager.getStage().stageWidth / 2;
				var stageCenterY:Number = LayerManager.getStage().stageHeight / 2;
				var dx:Number = stageCenterX - pt.x;
				var dy:Number = stageCenterY - pt.y;
				_moveW = _map.x + dx;
				_moveH = _map.y + dy;
				doMove(_map.x + dx, _map.y + dy, duration, easeFun, dispatchEvent);
			}
		}

		public function resizeImp():void
		{
			onResize();
		}
		
		public function addMoveListener(listener:Function, priority:int=0, useWeakReference:Boolean=false):void
		{
			addEventListener("move", listener, false, priority, useWeakReference);
		}

		public function removeMoveListener(listener:Function):void
		{
			removeEventListener("move", listener, false);
		}
		
		protected function fireMove():void
		{
			this.dispatchEvent(new Event("move"));
		}
		
		/**
		 * 销毁
		 * */
		public function destroy():void
		{
			_map.removeEventListener(Event.ADDED_TO_STAGE, onAddToStage);
			_map.removeEventListener(Event.REMOVED_FROM_STAGE, onRemovedFromStage);
			_map.removeEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
			if(_map.stage)
			{
				_map.stage.removeEventListener(Event.RESIZE, onResize);
				_map.stage.removeEventListener(Event.MOUSE_LEAVE, onLeaveHandler);
				_map.stage.removeEventListener(MouseEvent.MOUSE_UP, onUpHandler);
				_map.stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMoveHandler);
			}
			_map = null;
		}
		
		public function setDragable(dragable:Boolean):void
		{
			_dragable = dragable;
		}
		
		/**
		 * 按分辨率来更新范围值
		 * */
		private function updateRect():void
		{
			if(_resizeWithStage)
			{
				_rectangle.x = _rectangle.y = 0;
				_rectangle.width = _map.stage.stageWidth;
				_rectangle.height = _map.stage.stageHeight;
			}
		}
		
		public function isDragable():Boolean
		{
			return _dragable;
		}
		
		/**
		 * 返回是否随着屏幕自动调整视界
		 * @return		
		 */
		public function isResizeWithStage():Boolean
		{
			return _resizeWithStage;
		}
		
		/**
		 * 是否正在拖曳
		 * @return 地图是否正在拖曳
		 */
		public function isDrag():Boolean
		{
			return _drag;
		}
		
		/**
		 * 返回当前地图的坐标,此坐标为正值。
		 * @return 具有x,y属性的点
		 */
		public function getCurrentPoint():Object
		{
			return {x:-_map.x, y:-_map.y};
		}
		
		public function getMap():DisplayObject
		{
			return _map;
		}
		
		public function get moveW():Number
		{
			return _moveW;
		}
		
		public function get moveH():Number
		{
			return _moveH;
		}
		
		/**
		 * 响应鼠标点击事件
		 * */
		private function onClickHandler(event:MouseEvent):void
		{
			trace(_map.parent.mouseX, _map.parent.mouseY, _map.parent.width, _map.parent.height);
			trace(_map.x, _map.y, _map.mouseX, _map.mouseY);
		}
		
	}
}